<?php
declare(strict_types=1);
/**
 * MineAdmin is committed to providing solutions for quickly building web applications
 * Please view the LICENSE file that was distributed with this source code,
 * For the full copyright and license information.
 * Thank you very much for using MineAdmin.
 *
 * @Author X.Mo<root@imoi.cn>
 * @Link   https://gitee.com/xmo/MineAdmin
 */

namespace App\Wxc\Service;

use App\System\Service\SystemUploadFileService;
use App\Wxc\Concern\ManageChannelsShopApp;
use App\Wxc\Enums\MiniProgramStatus;
use App\Wxc\Enums\SharerFormStatus;
use App\Wxc\Mapper\WxcSharerFormMapper;
use App\Wxc\Model\WxcSharerForm;
use App\Wxc\Service\Input\SendMpMsgInput;
use App\Wxc\Service\Input\SharerFormAuditInput;
use App\Wxc\Service\Input\SharerFormInput;
use App\Wxc\Service\Query\SharerFormQuery;
use Carbon\Carbon;
use Deepwell\ChannelsShop\Api\Sharer\Request\BindRequest;
use Deepwell\EasyQuery\Concern\QueryService;
use Exception;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpMessage\Upload\UploadedFile;
use Mine\Abstracts\AbstractService;
use Mine\Exception\NormalStatusException;
use Psr\Log\LoggerInterface;

/**
 * 享员申请单服务类
 * @method WxcSharerForm|null QueryOne(?SharerFormQuery $input = null)
 */
class WxcSharerFormService extends AbstractService
{
    /**
     * @var WxcSharerFormMapper
     */
    public $mapper;

    use QueryService;

    use ManageChannelsShopApp;

    #[Inject]
    protected LoggerInterface $logger;

    public function __construct(WxcSharerFormMapper $mapper)
    {
        $this->mapper = $mapper;
        $this->queryModelClassName = WxcSharerForm::class;
    }

    /**
     * 添加一个申请
     * @param SharerFormInput $input
     * @return WxcSharerForm
     * @throws Exception
     */
    public function add(SharerFormInput $input)
    {
        // 检测是否存在待处理的申请单
        $get = new SharerFormQuery();
        $get->site_id = $input->site_id;
        $get->shop_id = $input->shop_id;
        $get->openid = $input->openid;
        $get->status = SharerFormStatus::Pending;
        $form = $this->queryOne($get);
        if ($form) {
            throw new Exception('已提交过申请，请勿重复提交');
        }

        return WxcSharerForm::create($input->toArray());
    }

    public function audit(SharerFormAuditInput $input)
    {
        return Db::transaction(function () use ($input) {
            $get = new SharerFormQuery();
            $get->form_id = $input->form_id;
            $form = $this->queryOne($get);
            if (!$form) {
                throw new Exception('申请单不存在');
            }
            if ($form->status === SharerFormStatus::Approved->value) {
                throw new Exception('申请单已处理');
            }
            // 如果审核不通过必须填写原因
            if ($input->status === SharerFormStatus::Rejected && !$input->reason) {
                throw new Exception('请填写审核不通过的原因');
            }
            $form->status = $input->status->value;
            $form->reason = $input->reason;
            $form->save();

            // 审核失败才发送订阅消息，审核通过商家会发一条小店邀请消息给用户确认
            if ($input->status === SharerFormStatus::Rejected) {
                $send = new SendMpMsgInput();
                $send->template_id = 'jqzspVWiWJA4oBnVkN3bJznfHUxq8g-Nx-x9MU1A-vo';
                $send->page = '/pages/sharer/form-list';
                $send->touser = $form->openid;
                $send->miniprogram_state = MiniProgramStatus::Developer;
                $send->data = [
                    'thing1' => ['value' => '分享员申请'],
                    'date2' => ['value' => Carbon::now()->format('Y-m-d H:i:s')],
                    'phrase5' => ['value' => '失败'],
                    'thing4' => ['value' => $input->reason],
                ];
                container()->get(WxcSharerMpService::class)->sendMessage($send);
            }

            // 审核通过则生成邀请二维码
            if ($input->status === SharerFormStatus::Approved) {
                $app = $this->initApplicationByAppId($form->app_id);
                $bind = new BindRequest();
                $bind->username = $form->wechat_account;
                $res = $app->sharer->bind($bind);
                if ($res->errcode) {
                    logger('wechat shop')->error('生成分享员邀请二维码失败：' . $res->errmsg);
                    throw new NormalStatusException($res->errmsg);
                }
                try {
                    // 将图片二进制流保存到本地
                    $dir = __DIR__ . '/../../../runtime/temp_files';
                    // 创建目录
                    if (!is_dir($dir)) {
                        mkdir($dir, 0755, true);
                    }
                    $binary = base64_decode($res->qrcodeImgBase64);
                    $imageInfo = getimagesizefromstring($binary);
                    $fileName = md5($binary) . '.' . explode('/', $imageInfo['mime'])[1];
                    $filePath = $dir . '/' . $fileName;
                    file_put_contents($filePath, $binary);
                    $uploadFile = new UploadedFile($filePath, filesize($filePath), UPLOAD_ERR_OK, $fileName, $imageInfo['mime']);
                    $uploadRes = container()->get(SystemUploadFileService::class)->upload($uploadFile, [
                        'path' => 'sharer-mp/bind-qrcode',
                    ]);
                    $form->bind_qrcode = get_file_url($uploadRes['url']);
                    if ($form->reason) {
                        $form->reason = '';
                    }
                    $form->save();
                } finally {
                    // 删除文件
                    unlink($filePath);
                }
            }

            return $form;
        });

    }
}